1 package org.apache.lucene.index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.Map;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.CountDownLatch;
22
23 import org.apache.lucene.analysis.MockAnalyzer;
24 import org.apache.lucene.document.Document;
25 import org.apache.lucene.document.Field;
26 import org.apache.lucene.search.IndexSearcher;
27 import org.apache.lucene.search.TermQuery;
28 import org.apache.lucene.search.TopDocs;
29 import org.apache.lucene.store.Directory;
30 import org.apache.lucene.util.LuceneTestCase;
31 import org.apache.lucene.util.TestUtil;
32
33 public class TestStressDeletes extends LuceneTestCase {
34
35
36
37 public void test() throws Exception {
38 final int numIDs = atLeast(100);
39 final Object[] locks = new Object[numIDs];
40 for(int i=0;i<locks.length;i++) {
41 locks[i] = new Object();
42 }
43
44 Directory dir = newDirectory();
45 IndexWriterConfig iwc = new IndexWriterConfig(new MockAnalyzer(random()));
46 final IndexWriter w = new IndexWriter(dir, iwc);
47 final int iters = atLeast(2000);
48 final Map<Integer,Boolean> exists = new ConcurrentHashMap<>();
49 Thread[] threads = new Thread[TestUtil.nextInt(random(), 2, 6)];
50 final CountDownLatch startingGun = new CountDownLatch(1);
51 final int deleteMode = random().nextInt(3);
52 for(int i=0;i<threads.length;i++) {
53 threads[i] = new Thread() {
54 @Override
55 public void run() {
56 try {
57 startingGun.await();
58 for(int iter=0;iter<iters;iter++) {
59 int id = random().nextInt(numIDs);
60 synchronized (locks[id]) {
61 Boolean v = exists.get(id);
62 if (v == null || v.booleanValue() == false) {
63 Document doc = new Document();
64 doc.add(newStringField("id", ""+id, Field.Store.NO));
65 w.addDocument(doc);
66 exists.put(id, true);
67 } else {
68 if (deleteMode == 0) {
69
70 w.deleteDocuments(new Term("id", ""+id));
71 } else if (deleteMode == 1) {
72
73 w.deleteDocuments(new TermQuery(new Term("id", ""+id)));
74 } else {
75
76 if (random().nextBoolean()) {
77 w.deleteDocuments(new Term("id", ""+id));
78 } else {
79 w.deleteDocuments(new TermQuery(new Term("id", ""+id)));
80 }
81 }
82 exists.put(id, false);
83 }
84 }
85 if (random().nextInt(500) == 2) {
86 DirectoryReader.open(w, random().nextBoolean()).close();
87 }
88 if (random().nextInt(500) == 2) {
89 w.commit();
90 }
91 }
92 } catch (Exception e) {
93 throw new RuntimeException(e);
94 }
95 }
96 };
97 threads[i].start();
98 }
99
100 startingGun.countDown();
101 for(Thread thread : threads) {
102 thread.join();
103 }
104
105 IndexReader r = w.getReader();
106 IndexSearcher s = newSearcher(r);
107 for(Map.Entry<Integer,Boolean> ent : exists.entrySet()) {
108 int id = ent.getKey();
109 TopDocs hits = s.search(new TermQuery(new Term("id", ""+id)), 1);
110 if (ent.getValue()) {
111 assertEquals(1, hits.totalHits);
112 } else {
113 assertEquals(0, hits.totalHits);
114 }
115 }
116 r.close();
117 w.close();
118 dir.close();
119 }
120 }